package com.eastfair.venueservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.venueservice.dao.ServiceOrderOperateLogMapper;
import com.eastfair.venueservice.dto.ServiceBookingDTO;
import com.eastfair.venueservice.dto.ServiceOrderDTO;
import com.eastfair.venueservice.dto.ServiceOrderOperateLogDTO;
import com.eastfair.venueservice.entity.ServiceBooking;
import com.eastfair.venueservice.entity.ServiceOrder;
import com.eastfair.venueservice.entity.ServiceOrderOperateLog;
import com.eastfair.venueservice.enums.ServiceOrderOperateLogOperateTypeEnum;
import com.eastfair.venueservice.service.ServiceOrderOperateLogService;
import com.eastfair.venueservice.vo.ServiceOrderOperateLogVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 服务订单操作记录
 * </p>
 *
 * @author dqq
 * @date 2022-12-16
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class ServiceOrderOperateLogServiceImpl extends SuperServiceImpl<ServiceOrderOperateLogMapper, ServiceOrderOperateLog> implements ServiceOrderOperateLogService {

    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<ServiceOrderOperateLog> modelList) {
        modelList.forEach(s -> s.setIsDeleted(BusinessConstant.YES));
        return R.successDef();
    }

    @Override
    protected R<Boolean> handlerSave(ServiceOrderOperateLog model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        return R.successDef();
    }

    @Override
    public Page<ServiceOrderOperateLogVO> listServiceOrderOperateLogVO(PageParams<ServiceOrderOperateLogDTO> pageParams) {
        log.info("listServiceOrderOperateLogVO - 分页查询订单操作记录VO列表, params={}", pageParams);
        ServiceOrderOperateLogDTO model = pageParams.getModel();
        Page<ServiceOrderOperateLog> pageParam = pageParams.buildPage();
        QueryWrapper<ServiceOrderOperateLog> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(ServiceOrderOperateLog::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(StrUtil.isNotBlank(model.getOrderNumber()), ServiceOrderOperateLog::getOrderNumber, model.getOrderNumber())
        ;
        Page<ServiceOrderOperateLog> page = page(pageParam, queryWrapper);
        Page<ServiceOrderOperateLogVO> voPage = new Page<>();
        BeanUtil.copyProperties(page, voPage);
        List<ServiceOrderOperateLog> list = page.getRecords();
        if (list == null || list.isEmpty()) {
            return voPage;
        }
        List<ServiceOrderOperateLogVO> voList = list
                .stream()
                .map(serviceOrderOperateLog -> BeanUtil.toBean(serviceOrderOperateLog, ServiceOrderOperateLogVO.class))
                .collect(Collectors.toList());
        voPage.setRecords(voList);
        return voPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceOrderOperateLog saveServiceOrderOperateLog(ServiceOrderOperateLogDTO serviceOrderOperateLogDTO) {
        log.info("saveServiceOrderOperateLog - 保存订单操作记录, serviceOrderOperateLogDTO={}", serviceOrderOperateLogDTO);
        ServiceOrderOperateLog serviceOrderOperateLog = BeanUtil.toBean(serviceOrderOperateLogDTO, ServiceOrderOperateLog.class);
        save(serviceOrderOperateLog);
        return serviceOrderOperateLog;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceOrderOperateLog updateServiceOrderOperateLog(ServiceOrderOperateLogDTO serviceOrderOperateLogDTO) {
        log.info("updateServiceOrderOperateLog - 更新订单操作记录, serviceOrderOperateLogDTO={}", serviceOrderOperateLogDTO);
        ServiceOrderOperateLog serviceOrderOperateLog = BeanUtil.toBean(serviceOrderOperateLogDTO, ServiceOrderOperateLog.class);
        updateById(serviceOrderOperateLog);
        return serviceOrderOperateLog;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean logAddOrderService(List<ServiceBookingDTO> newServiceBookingList, List<ServiceBooking> oldServiceBookingList) {
        if (newServiceBookingList == null || newServiceBookingList.isEmpty()) {
            return false;
        }
        // 添加之前的服务项ID列表
        List<Long> oldServiceItemIdList = oldServiceBookingList
                .stream()
                .map(ServiceBooking::getServiceItemId)
                .collect(Collectors.toList());
        // 找到哪些服务是订单新增的服务
        newServiceBookingList = newServiceBookingList
                .stream()
                .filter(serviceBookingDTO -> !oldServiceItemIdList.contains(serviceBookingDTO.getServiceItemId()))
                .collect(Collectors.toList());
        // 记录日志
        for (ServiceBookingDTO serviceBooking : newServiceBookingList) {
            ServiceOrderOperateLogDTO serviceOrderOperateLogDTO = new ServiceOrderOperateLogDTO();
            serviceOrderOperateLogDTO.setOrderNumber(serviceBooking.getOrderNumber());
            serviceOrderOperateLogDTO.setOperateType(ServiceOrderOperateLogOperateTypeEnum.ADD_ORDER_SERVICE.getCode());
            serviceOrderOperateLogDTO.setOperateId(ContextUtil.getUserId());
            serviceOrderOperateLogDTO.setOperateName(ContextUtil.getRealName());
            serviceOrderOperateLogDTO.setOperateTime(LocalDateTime.now());
            String operateContent = serviceOrderOperateLogDTO.getOperateName() + "添加了订单服务" + serviceBooking.getServiceName();
            serviceOrderOperateLogDTO.setOperateContent(operateContent);
            saveServiceOrderOperateLog(serviceOrderOperateLogDTO);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean logUpdateOrderService(List<ServiceBookingDTO> newServiceBookingList, List<ServiceBooking> oldServiceBookingList) {
        if (newServiceBookingList == null || newServiceBookingList.isEmpty()) {
            return false;
        }
        // 添加之前的服务项ID列表
        Map<Long, ServiceBooking> oldServiceBookingMap = new HashMap<>(16);
        for (ServiceBooking olServiceBooking: oldServiceBookingList) {
            oldServiceBookingMap.put(olServiceBooking.getServiceItemId(), olServiceBooking);
        }
        // 找到哪些服务是订单新增的服务
        for (ServiceBookingDTO newServiceBooking : newServiceBookingList) {
            ServiceBooking oldServiceBooking = oldServiceBookingMap.get(newServiceBooking.getServiceItemId());
            // 说明是添加的服务
            if (oldServiceBooking == null) {
                continue;
            }
            // 只能编辑订单服务的预定数量和折扣，这两项相等说明未编辑服务
            Long oldBookingNum = oldServiceBooking.getBookingNum();
            BigDecimal oldDiscount = oldServiceBooking.getDiscount();
            if (oldBookingNum.equals(newServiceBooking.getBookingNum()) && oldDiscount.compareTo(newServiceBooking.getDiscount()) == 0) {
                continue;
            }
            ServiceOrderOperateLogDTO serviceOrderOperateLogDTO = new ServiceOrderOperateLogDTO();
            serviceOrderOperateLogDTO.setOrderNumber(newServiceBooking.getOrderNumber());
            serviceOrderOperateLogDTO.setOperateType(ServiceOrderOperateLogOperateTypeEnum.UPDATE_ORDER_SERVICE.getCode());
            serviceOrderOperateLogDTO.setOperateId(ContextUtil.getUserId());
            serviceOrderOperateLogDTO.setOperateName(ContextUtil.getRealName());
            serviceOrderOperateLogDTO.setOperateTime(LocalDateTime.now());
            String operateContent = serviceOrderOperateLogDTO.getOperateName() + "编辑了订单服务" + newServiceBooking.getServiceName();
            if (!oldBookingNum.equals(newServiceBooking.getBookingNum())) {
                operateContent += "，修改数量为" + newServiceBooking.getBookingNum();
            }
            if (oldDiscount.compareTo(newServiceBooking.getDiscount()) != 0) {
                operateContent += "，修改折扣为" + newServiceBooking.getDiscount();
            }
            serviceOrderOperateLogDTO.setOperateContent(operateContent);
            saveServiceOrderOperateLog(serviceOrderOperateLogDTO);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean logUpdateOrderAmount(ServiceOrder newServiceOrder, ServiceOrder oldServiceOrder) {
        // 为修改订单金额
        if (oldServiceOrder.getShouldPayAmount().compareTo(newServiceOrder.getShouldPayAmount()) == 0) {
            return false;
        }
        // 记录日志
        ServiceOrderOperateLogDTO serviceOrderOperateLogDTO = new ServiceOrderOperateLogDTO();
        serviceOrderOperateLogDTO.setOrderNumber(newServiceOrder.getOrderNumber());
        serviceOrderOperateLogDTO.setOperateType(ServiceOrderOperateLogOperateTypeEnum.UPDATE_ORDER_AMOUNT.getCode());
        serviceOrderOperateLogDTO.setOperateId(ContextUtil.getUserId());
        serviceOrderOperateLogDTO.setOperateName(ContextUtil.getRealName());
        serviceOrderOperateLogDTO.setOperateTime(LocalDateTime.now());
        String operateContent = serviceOrderOperateLogDTO.getOperateName() + "修改订单金额为¥" + newServiceOrder.getShouldPayAmount();
        serviceOrderOperateLogDTO.setOperateContent(operateContent);
        saveServiceOrderOperateLog(serviceOrderOperateLogDTO);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean logCancelServiceOrder(ServiceOrder serviceOrder) {
        ServiceOrderOperateLogDTO serviceOrderOperateLogDTO = new ServiceOrderOperateLogDTO();
        serviceOrderOperateLogDTO.setOrderNumber(serviceOrder.getOrderNumber());
        serviceOrderOperateLogDTO.setOperateType(ServiceOrderOperateLogOperateTypeEnum.CANCEL_ORDER.getCode());
        serviceOrderOperateLogDTO.setOperateId(ContextUtil.getUserId());
        serviceOrderOperateLogDTO.setOperateName(ContextUtil.getRealName());
        serviceOrderOperateLogDTO.setOperateTime(LocalDateTime.now());
        String operateContent = serviceOrderOperateLogDTO.getOperateName() + "取消了订单";
        serviceOrderOperateLogDTO.setOperateContent(operateContent);
        saveServiceOrderOperateLog(serviceOrderOperateLogDTO);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean logApplyOrderInvoice(ServiceOrderDTO serviceOrderDTO) {
        return false;
    }

    @Override
    public void asyncLogAddOrderService(List<ServiceBookingDTO> newServiceBookingList, List<ServiceBooking> oldServiceBookingList) {
        threadPoolTaskExecutor.execute(() -> logAddOrderService(newServiceBookingList, oldServiceBookingList));
    }

    @Override
    public void asyncLogUpdateOrderService(List<ServiceBookingDTO> newServiceBookingList, List<ServiceBooking> oldServiceBookingList) {
        threadPoolTaskExecutor.execute(() -> logUpdateOrderService(newServiceBookingList, oldServiceBookingList));
    }

    @Override
    public void asyncLogUpdateOrderAmount(ServiceOrder newServiceOrder, ServiceOrder oldServiceOrder) {
        threadPoolTaskExecutor.execute(() -> logUpdateOrderAmount(newServiceOrder, oldServiceOrder));
    }

    @Override
    public void asyncLogCancelServiceOrder(ServiceOrder serviceOrder) {
         threadPoolTaskExecutor.execute(() -> logCancelServiceOrder(serviceOrder));
    }
}
